/*
 * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.
 *
 * Copyright (C) 2016-2023 Philip Helger (www.helger.com)
 * philip[at]helger[dot]com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitee.wsl.time.calendar

import kotlinx.datetime.TimeZone

/**
 *
 *
 * This implementation of the Calendar may be used (you don't have to) as a base
 * class for more sophisticated one's. It merely implements the base
 * functionality required by each Calendar.
 *
 *
 *
 * Regarded as base functionality is the treatment of base calendars. Base
 * calendar allow you to chain (stack) as much calendars as you may need. For
 * example to exclude weekends you may use WeeklyCalendar. In order to exclude
 * holidays as well you may define a WeeklyCalendar instance to be the base
 * calendar for HolidayCalendar instance.
 *
 *
 * @see com.helger.quartz.Calendar
 *
 * @author Juergen Donnerstag
 * @author James House
 */
abstract class AbstractCalendar(
    override var baseCalendar: Calendar?=null,
    override var description: String = "",
    var timeZone: TimeZone? = null
) : Calendar{

    /**
     * Copy constructor
     *
     * @param aOther
     * Calendar to copy from. May not be `null`.
     */
    protected constructor(aOther: AbstractCalendar):this(aOther.baseCalendar, aOther.description, aOther.timeZone)

    /**
     *
     *
     * Check if date/time represented by timeStamp is included. If included return
     * true. The implementation of AbstractCalendar simply calls the base
     * calendars isTimeIncluded() method if base calendar is set.
     *
     *
     * @see com.helger.quartz.Calendar.isTimeIncluded
     */
    override fun isTimeIncluded(timeStamp: Long): Boolean {
        if (timeStamp <= 0) throw IllegalArgumentException("timeStamp must be greater 0")

        return baseCalendar == null || baseCalendar!!.isTimeIncluded(timeStamp)
    }

    /**
     *
     *
     * Determine the next time (in milliseconds) that is 'included' by the
     * Calendar after the given time. Return the original value if timeStamp is
     * included. Return 0 if all days are excluded.
     *
     *
     * @see com.helger.quartz.Calendar.getNextIncludedTime
     */
    override fun getNextIncludedTime(timeStamp: Long): Long {
        if (timeStamp <= 0) throw IllegalArgumentException("timeStamp must be greater 0")

        if (baseCalendar != null) return baseCalendar!!.getNextIncludedTime(timeStamp)

        return timeStamp
    }

    /**
     * Build a `[Calendar]` for the given timeStamp. The new
     * Calendar will use the `AbstractCalendar` time zone if it is not
     * `null`.
     */
    /*protected fun createJavaCalendar(timeStamp: Long): Calendar {
        val calendar: Calendar = createJavaCalendar()
        calendar.setTime(Date(timeStamp))
        return calendar
    }*/

    /**
     * Build a `[Calendar]` with the current time. The new
     * Calendar will use the `AbstractCalendar` time zone if it is not
     * `null`.
     */
    /*protected fun createJavaCalendar(): Calendar {
        return Calendar.getInstance(
            if (timeZone != null) timeZone else TimeZone.getDefault(),
            Locale.getDefault(Locale.Category.FORMAT)
        )
    }*/

    /**
     * Returns the start of the given day as a `[Calendar]`. This
     * calculation will take the `AbstractCalendar` time zone into
     * account if it is not `null`.
     *
     * @param timeInMillis
     * A time containing the desired date for the start-of-day time
     * @return A `[Calendar]` set to the start of the given day.
     */
    /*protected fun getStartOfDayJavaCalendar(timeInMillis: Long): Calendar {
        val startOfDay: Calendar = createJavaCalendar(timeInMillis)
        startOfDay.set(Calendar.HOUR_OF_DAY, 0)
        startOfDay.set(Calendar.MINUTE, 0)
        startOfDay.set(Calendar.SECOND, 0)
        startOfDay.set(Calendar.MILLISECOND, 0)
        return startOfDay
    }*/

    /**
     * Returns the end of the given day `[Calendar]`. This
     * calculation will take the `AbstractCalendar` time zone into
     * account if it is not `null`.
     *
     * @param timeInMillis
     * a time containing the desired date for the end-of-day time.
     * @return A `[Calendar]` set to the end of the given day.
     */
    /*protected fun getEndOfDayJavaCalendar(timeInMillis: Long): Calendar {
        val endOfDay: Calendar = createJavaCalendar(timeInMillis)
        endOfDay.set(Calendar.HOUR_OF_DAY, 23)
        endOfDay.set(Calendar.MINUTE, 59)
        endOfDay.set(Calendar.SECOND, 59)
        endOfDay.set(Calendar.MILLISECOND, 999)
        return endOfDay
    }*/
}
